package com.ck.chuangke.service.impl;

import com.ck.chuangke.service.CkDeviceInfoService;
import com.ck.common.service.OperationLogService;
import com.ck.company.service.CpDeviceInfoService;
import com.ck.constant.*;
import com.ck.dao.DeviceMapper;
import com.ck.dao.DeviceSettingMapper;
import com.ck.dao.DeviceUpgradeMapper;
import com.ck.dao.ProgramMapper;
import com.ck.exception.ServiceException;
import com.ck.model.chuangke.dto.CkDeviceDetailDTO;
import com.ck.model.chuangke.vo.*;
import com.ck.model.common.DeviceSetting;
import com.ck.model.common.DeviceUpgrade;
import com.ck.model.common.OperationLog;
import com.ck.model.common.User;
import com.ck.model.common.page.PageInfo;
import com.ck.model.common.vo.ProgramSimpleVO;
import com.ck.util.DateUtils;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Lists;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;


@Service(value = "ckDeviceInfoService")
public class CkDeviceInfoServiceImpl implements CkDeviceInfoService {
	private final Logger logger = LoggerFactory.getLogger(this.getClass());
	@Autowired
	OperationLogService operationLogService;
	@Autowired
	CpDeviceInfoService cpDeviceInfoService;
	@Autowired
	DeviceMapper deviceMapper;
	@Autowired
	ProgramMapper programMapper;
	@Autowired
	DeviceSettingMapper settingMapper;
	@Autowired
	DeviceUpgradeMapper deviceUpgradeMapper;
	/**
	 * 获取终端总数
	 * @return
	 */
	@Override
	public Long getDeviceCount() {
		return deviceMapper.getDeviceCount();
	}

	/**
	 * 根据大区查询终端总数
	 * @param region 大区：东北NE，华北NC，华中CC，华东EC，华南SC，西北WN，西南WS
	 * @return
	 */
	@Override
	public Long getDeviceCountByRegion(String region) {
		return deviceMapper.getDeviceCountByRegion(region);
	}

	/**
	 * 根据大区和状态查询终端总数
	 * @param region 大区：东北NE，华北NC，华中CC，华东EC，华南SC，西北WN，西南WS
	 * @param status 状态：0.在线; 1.离线
	 * @return
	 */
	@Override
	public Long getDeviceCountByRegionAndStatus(String region, Integer status) {
		return deviceMapper.getDeviceCountByRegionAndStatus(region, status);
	}
	
	/**
     * 创客后台查看所有终端信息列表
     * @param startTime  终端创建时间-开始
     * @param endTime    终端创建时间-结束
     * @param deviceCode  终端机器码
     * @param deviceMac   终端mac地址
     * @param companyName 商家名称
     * @param province 省
     * @param city 市
     * @param area 地区
     * @param pageNum  
     * @param pageSize
     * @return
     */
	@Override
	public PageInfo<CkDeviceInfoListVO> listByPage(Long startTime, Long endTime, String deviceCode, String deviceMac,
			String companyName, String deviceName,String province, String city, String area, Integer pageNum, Integer pageSize) {
		pageNum = (pageNum == null || pageNum < 0 ? PageConstant.DEFAULT_PAGE_NUM : pageNum);
		pageSize = (pageSize == null || pageSize < 0 ? PageConstant.DEFAULT_PAGE_SIZE : pageSize);
		PageHelper.startPage(pageNum, pageSize);
		Page<CkDeviceInfoListVO> page = deviceMapper.listByPageForCk( startTime,  endTime,  deviceCode,  deviceMac,
				 companyName,  deviceName, province,  city,  area );
		if(page == null) {
            return new PageInfo<>(pageNum, pageSize, 0, Lists.newArrayList());
        }
		PageInfo<CkDeviceInfoListVO> pageInfo = new PageInfo<>();
		pageInfo.setList(page.getResult());
		pageInfo.setPageNum(page.getPageNum());
		pageInfo.setPageSize(page.getPageSize());
		pageInfo.setTotal(page.getTotal());
		return pageInfo;
	}
	
	 /**
     * 创客后台条件导出终端信息列表
     * @param startTime  终端创建时间-开始
     * @param endTime    终端创建时间-结束
     * @param deviceCode  终端机器码
     * @param deviceMac   终端mac地址
     * @param companyName 商家名称
     * @param deviceName 终端名称（备注）
     * @param province 省
     * @param city 市
     * @param area 地区
     * @return
     */
	@Override
	public List<CkDeviceInfoListExportVO> exportDeviceReport(Long start, Long end, String deviceCode, String deviceMac,
			String companyName,String deviceName, String province, String city, String area) {
		return deviceMapper.listByExportForCk( start,  end,  deviceCode,  deviceMac, companyName, deviceName, province,  city,  area );
	}
	
	/**
	 * 创客后台查询终端日志列表
	 * @param start  日志上传时间-开始
	 * @param end 日志上传时间-结束
	 * @param deviceCode  终端唯一编码
	 * @param logType 日志类型 @see LogType
	 * @param pageNum
	 * @param pageSize
	 * @return
	 */
	@Override
	public PageInfo<CkDeviceLogListVO> listDeviceLogs(Long start, Long end, String deviceCode, String logType,
			Integer pageNum, Integer pageSize) {
		pageNum = (pageNum == null || pageNum < 0 ? PageConstant.DEFAULT_PAGE_NUM : pageNum);
		pageSize = (pageSize == null || pageSize < 0 ? PageConstant.DEFAULT_PAGE_SIZE : pageSize);
		PageHelper.startPage(pageNum, pageSize);
		Page<CkDeviceLogListVO> page = deviceMapper.listDeviceLogs( start,  end,  deviceCode,  logType);
		if(page == null) {
            return new PageInfo<>(pageNum, pageSize, 0, Lists.newArrayList());
        }
		PageInfo<CkDeviceLogListVO> pageInfo = new PageInfo<>();
		pageInfo.setList(page.getResult());
		pageInfo.setPageNum(page.getPageNum());
		pageInfo.setPageSize(page.getPageSize());
		pageInfo.setTotal(page.getTotal());
		return pageInfo;
	}
	
	/**
	 * 创客查看终端详情
	 */
	@Override
	public CkDeviceDetailVO getDeviceDetail(String deviceCode) {
		List<CkDeviceDetailDTO> list = deviceMapper.getDeviceDetailForCk(deviceCode);
		CkDeviceDetailDTO dto = CollectionUtils.isNotEmpty(list) ? list.get(0) : null;
		if ( dto != null ) {
			CkDeviceDetailVO deviceInfoVO = generateDeviceInfoVO(dto);
			setProgramSimpleInfo(dto, deviceInfoVO);
			return deviceInfoVO;
		} 
		return null;
	}

	private void setProgramSimpleInfo(CkDeviceDetailDTO dto,CkDeviceDetailVO vo) {
		
		// 记录program_version
		List<String> listAll = new ArrayList<>();
		List<String> currentDowning = new ArrayList<>();// 当前正在下载节目
		List<String> currentPlaying = new ArrayList<>();// 当前正在播放节目
		List<String> waitPlay = new ArrayList<>();// 等待播放节目
		String currentDownloadingStr =  dto.getCurrentDownloadingProgramVer();
		if ( StringUtils.isNotBlank(currentDownloadingStr) ) {
			String[] split = currentDownloadingStr.split(",");
			currentDowning = Arrays.asList(split);
			listAll.addAll(currentDowning);
		}
		String currentPlayingStr =  dto.getCurrentPlayingProgramVer();
		if ( StringUtils.isNotBlank(currentPlayingStr) ) {
			String[] split = currentPlayingStr.split(",");
			currentPlaying = Arrays.asList(split);
			listAll.addAll(currentPlaying);
		}
		String waitPlayStr =  dto.getWaitPlayProgramVer();
		if ( StringUtils.isNotBlank(waitPlayStr) ) {
			String[] split = waitPlayStr.split(",");
			waitPlay = Arrays.asList(split);
			listAll.addAll(waitPlay);
		}
		
		// 批量查询节目基础信息
		if ( !CollectionUtils.isEmpty(listAll) ) {
			List<ProgramSimpleVO> programs = programMapper.getProgramSimpleInfoByVersion(listAll);
			vo.setProgramQueue(programs);
			for ( ProgramSimpleVO pro : programs ) {
				if  (currentDowning.contains(pro.getProgramVersion())) {
					pro.setState(ProgramStateType.CURRENT_DOWNLOADING.getProgramStateType());
					continue;
				}
				if  (currentPlaying.contains(pro.getProgramVersion())) {
					pro.setState(ProgramStateType.CURRENT_PLAYING.getProgramStateType());
					continue;
				}
				if  (waitPlay.contains(pro.getProgramVersion())) {
					pro.setState(ProgramStateType.WAIT_PLAY.getProgramStateType());
					continue;
				}
			}
		}
	}
	
	private CkDeviceDetailVO generateDeviceInfoVO(CkDeviceDetailDTO dto) {
		CkDeviceDetailVO vo = new CkDeviceDetailVO();
		vo.setCreateTime(toYmdhms(dto.getCreateTime()));
		vo.setDeviceMac(dto.getDeviceMac());
		vo.setDeviceName(dto.getDeviceName());
		vo.setDeviceCode(dto.getDeviceCode());
		vo.setDeviceStatus(dto.getDeviceStatus() != null && dto.getDeviceStatus() == BusinessConstant.DEVICE_INFO_STATUS_ON_LINE ? "在线" : "离线");
		vo.setDeviceModel(dto.getDeviceModel());
		vo.setProvince(dto.getProvince());
		vo.setCity(dto.getCity());
		vo.setArea(dto.getArea());
		vo.setDetailAddr(dto.getDetailAddr());
		vo.setExternalIp(dto.getExternalIp());
		vo.setIntranetIp(dto.getIntranetIp());
		vo.setCompanyName(dto.getCompanyName());
		vo.setCompanyCode(dto.getCompanyCode());
		vo.setLastRebootTime(toYmdhms(dto.getLastRebootTime()));
		vo.setContinuousWorkingHours(dto.getContinuousWorkingHours());
		vo.setSoftwareVersion(dto.getSoftwareVersion());
		vo.setSoftwareUpgradeTime(toYmdhms(dto.getSoftwareUpgradeTime()));
		vo.setFirmwareVersion(dto.getFirmwareVersion());
		vo.setFirmwareUpgrageTime(toYmdhms(dto.getFirmwareUpgrageTime()));
		vo.setModemSn(dto.getModemSn());
		vo.setModemImei(dto.getModemImei());
		vo.setModemNetworkType(dto.getModemNetworkType());
		vo.setModemSignalStrength(dto.getModemSignalStrength());
		vo.setModemSendBytes(dto.getModemSendBytes());
		vo.setModemReceivedBytes(dto.getModemReceivedBytes());
		vo.setModemLastLoginTime(toYmdhms(dto.getLastRebootTime()));
		vo.setReceivingAverageSpeed(dto.getReceivingAverageSpeed());
		vo.setHistoryTotalFlow(dto.getHistoryTotalFlow());
		vo.setSimIsReign(Boolean.TRUE.equals(dto.getSimIsReign()) ? "是" : "否");
		vo.setSimIccid(dto.getSimIccid());
		vo.setSimImei(dto.getSimImei());
		vo.setTimeShutdown(dto.getTimeShutdown());
		vo.setTimeBoot(dto.getTimeBoot());
		vo.setTimeShutdownScreen(dto.getTimeShutdownScreen());
		vo.setTimeBootScreen(dto.getTimeBootScreen());
		vo.setDeviceVolume(dto.getDeviceVolume());
		return vo;
	}
	
	private String toYmdhms(Long time) {
		if ( time == null ) {
			return "";
		}
		try {
			return DateUtils.longTimeStampToStringDate(time, DateUtils.PATTEN_YMD_HMS);
		} catch (Exception e) {
			return "";
		}
	}

	@Override
	@Transactional(readOnly = false, rollbackFor = Exception.class)
	public void deviceUpgrade(Integer upgradeType, String deviceCodes, Long deviceUpgradeId, User user,String operationIp) throws ServiceException {
		DeviceUpgrade deviceUpgrade = deviceUpgradeMapper.getDeviceUpgradeById(deviceUpgradeId);
		if ( deviceUpgrade == null ) {
			throw new ServiceException("升级信息不存在，请检查参数是否正确！");
		}
		List<String> codes = null;
		Long serialNo = System.currentTimeMillis(); // 记录批次号（时间戳）保证数据库跟缓存中更新时间一致
		String module = "";
		if ( StringUtils.isNotBlank(deviceCodes) ) {
			DeviceSetting setting = new DeviceSetting();
			setting.setUpdateTime(serialNo);
			codes = Arrays.asList(deviceCodes.split(","));
			if (BusinessConstant.DEVICE_UPGRADE_TYPE_SOFTWARE == upgradeType) {
				setting.setSoftwareUpgradeId(deviceUpgradeId);
				module = ModuleConstant.MODULE_SYSTEM + "-" + ModuleConstant.MODULE_SOFTWARE_MNG;
			} else if (BusinessConstant.DEVICE_UPGRADE_TYPE_FIRMWARE == upgradeType){
				setting.setFirmwareUpgradeId(deviceUpgradeId);
				module = ModuleConstant.MODULE_SYSTEM + "-" + ModuleConstant.MODULE_FIRMWARE_MNG;
			}
			settingMapper.updateDeviceSetting(setting, codes, null);
		}
		
		// 保存操作日志
		saveLog( operationIp, user, "设置终端升级信息，升级为：[" + deviceUpgrade.getUpgradeName() + "]",module);
		
		// 刷新缓存,不影响事务操作
		try {
			DeviceSettingType settingType = (BusinessConstant.DEVICE_UPGRADE_TYPE_SOFTWARE == upgradeType ? DeviceSettingType.SOFTWARE_UPGRADE : DeviceSettingType.FIRMWARE_UPGRADE);
			cpDeviceInfoService.flushDeviceStateCache(null, settingType, codes, serialNo);
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("设置终端升级信息，更新缓存异常：" + e.getMessage(),e);
		}
	}
	
	private void saveLog(String operationIp,User user,String keyWords,String module) {
		// 保存操作日志
		OperationLog operationLog = new OperationLog();
		operationLog.setOperationContent(keyWords);
		operationLog.setOperationModule(module);
		operationLog.setOperationStatus(BusinessConstant.OPERATION_LONG_OPERATION_STATUS_SUCCESS);
		operationLog.setOperationTime(System.currentTimeMillis());
		operationLog.setUserName(user.getUserName());
		operationLog.setRealname(user.getRealname());
		operationLog.setCopmanyCode(user.getCompanyCode());
		operationLog.setOperationIp(operationIp);
		operationLogService.saveOperationLog(operationLog);
	}
	
	/**
	 * 查询所有终端中所有的mips版本号
	 *
	 * @return List<String>
	 */
	@Override
	public List<String> listAllSoftwareVersion() {
		return deviceMapper.listAllSoftwareVersion();
	}
	
	/**
	 * 查询所有终端中所有的固件版本号
	 *
	 * @return List<String>
	 */
	@Override
	public List<String> listAllFirmwareVersion() {
		return deviceMapper.listAllFirmwareVersion();
	}
	
	/**
     * 终端升级分页筛选查询终端
     * @param softVer  软件版本
     * @param firmVer  固件版本 
     * @param deviceStatus  终端状态（在线OR离线）
     * @param modelName 终端型号
     * @param province 省
     * @param city 市
     * @param area 区
     * @param companyName 商家名称
     * @param pageNum
     * @param pageSize
     * @return
     */
	@Override
	public PageInfo<CkUpgradeDeviceListVO> listUpgradeDeviceByPage(String softVer, String firmVer, Integer deviceStatus,
			String modelName, String province, String city, String area, String companyName, Integer pageNum,
			Integer pageSize) {
		if (pageNum == null) {
			pageNum = PageConstant.DEFAULT_PAGE_NUM;
		}
		if (pageSize == null) {
			pageSize = PageConstant.DEFAULT_PAGE_SIZE;
		}
		PageHelper.startPage(pageNum, pageSize);
		Page<CkUpgradeDeviceListVO> page = deviceMapper.listUpgradeDeviceByPage(softVer, firmVer, deviceStatus, modelName, province, city, area, companyName);
		PageInfo<CkUpgradeDeviceListVO> pageInfo = new PageInfo<>();
		if (page == null) {
			return pageInfo;
		}
		pageInfo.setList(page.getResult());
		pageInfo.setTotal(page.getTotal());
		pageInfo.setPageNum(page.getPageNum());
		pageInfo.setPageSize(page.getPageSize());
		return pageInfo;
	}
	
	/**
	 * 条件查询终端统计符合条件的终端数量
     * @param softVer  软件版本
     * @param firmVer  固件版本 
     * @param deviceStatus  终端状态（在线OR离线）
     * @param modelName 终端型号
     * @param province 省
     * @param city 市
     * @param area 区
     * @param companyName 商家名称
	 * @return
	 */
	@Override
	public Long getDeviceCountByCondition(String softVer, String firmVer, Integer deviceStatus, String modelName,
			String province, String city, String area, String companyName) {
		Long count = deviceMapper.getDeviceCountByCondition(softVer, firmVer, deviceStatus, modelName, province, city, area, companyName);
		return count == null ? 0L : count;
	}
}
